#ifndef GOD_RAY_RENDERER_H_
#define GOD_RAY_RENDERER_H_

#include "SkyBox.h"
#include "ResourceManager.h"
class DirectXMesh;

class GodRayRenderer
{
public:
    GodRayRenderer();
    /* Creation, and destruction */
    void Initialise(ID3DXEffect* effect, D3DXVECTOR3* lightPosWorldSpace,
                    int screenX, int screenY, D3DFORMAT textureFormat, int shadowMapSize,
                    bool shouldShadowMap, D3DXMATRIXA16* lightView, D3DXMATRIXA16* lightProj,
                    bool shouldGodRay, bool externalTexture, bool externalMesh, int numberOfPasses,
                    DirectXMesh* sunShape, Texture sunTexture,
                    Texture ptrToTexture, bool addNoise, Texture noiseTex, bool skyBox);
    void ShutDown();
    /* Used in the rendering loop as follows */
    /*
    YourGameClass::Render()
    {
        for(int i = 0; i < m_GodRayRenderer.GetNumberOfPasses(); ++i)
        {
            if(m_GodRayRenderer.ShouldRenderThisPass(i))->
                Internally calls m_GodRayRenderer::ManagePass(i);->
                    Internally Sets Matrices Values inside Shader based on PTR's
            {
                RenderScene();
            }
        }
    }
    */
    void InitialiseSkyBox(int size_x, int size_y, int size_z,
        float pos_x, float pos_y, float pos_z);
    void InitialiseSkyDome(float pos_x, float pos_y, float pos_z, int r);
    int GetNumberOfPasses() const;
    bool ShouldRenderThisPass(int whichPass);
    bool ShouldRenderDebugOnly(int pass);
    void ManagePass(int whichPass);
    void RenderFinalTexture();

    /* Set Functions for the render loop */
    void SetShadowMapping(bool shouldMap);
    void SetDownSampleRays(bool shouldDownSample);
    void SetNoiseAddition(bool addsRain);
    /* Get Functions for the render loop */
    bool IsShadowMapping() const {return m_shouldShadowMap;}
    bool IsAddingNoise() const {return m_shouldAddNoise;}
    void SetLightSourceTexture(Texture t){m_lightSourceTexture = t;}
private:
    //At the very least, this class will render one image into this texture
    LPDIRECT3DTEXTURE9 m_sceneTexture;
    //through this effect
    ID3DXEffect* m_effect;
    //With this skybox
    bool m_shouldSkyBox;
    SkyBox m_skyBox;
/************************************************************************/
/* SHADOW MAPPING VARIABLES                                             */
/************************************************************************/
    bool m_shouldShadowMap;
    int m_shadowMapSize;
    /* lights Matrix */
    D3DXMATRIXA16* m_lightViewMatrix;
    D3DXMATRIXA16* m_lightProjMatrix;
    /* lights position in screen co-ordinates and world coordinates */
    D3DXVECTOR2 m_lightPositionScreenSpace;
    D3DXVECTOR2 m_lightDirectionScreenSpace;
    D3DXVECTOR3* m_lightPositionWorldSpace;
    //This is the shadow map texture
    Texture m_shadowMap;

/************************************************************************/
/*  ADDING NOISE VARIABLES                                              */
/************************************************************************/
    bool m_shouldAddNoise;
    /* Externally managed texture */
    Texture m_noiseTexture;
    Texture m_subtractedLightTexture;
    Texture m_LightWithNoise;

/************************************************************************/
/*  GOD RAY VARIABLES                                                   */
/************************************************************************/
    bool m_shouldGodRay;
    //we render the light texture to this one in world space
    Texture m_lightTextureWorld;
    //The scene is rendered here as black
    Texture m_darkPassTexture;
    //The scene is rendered here as additive of the light texture and the black pass
    Texture m_addititiveDarkPass;
    //This is the texture storing the god rays
    Texture m_godRayTexture;
    //This is the final belnded texture
    Texture m_finalTexture;
    //Used for creating the sun texture if using a mesh
    DirectXMesh* m_sunShape;
    Texture m_sunTexture;
    bool m_usingSunMesh;
    float m_sunRotation;
    //Used for creating the sun texture if using another texture(externally managed)
    Texture m_lightSourceTexture;
    bool m_usingExternalTexture;

/************************************************************************/
/* HELPER VARIABLES                                                     */
/************************************************************************/
    //variables of the god ray algorithm
    float m_gDensity;
    float m_gIllumDecay;
    float m_gWeight;
    float m_gDecay;
    float m_gExposure;
    int m_numGodRayPasses;
    //The color threshold of the god ray algorithm
    float m_gTHold;
    //The y trans of the noise texture 
    float m_gVal;
    // Half angle of light in rads
    float m_gCosTheta;
    //Used for rendering a full screenQuad
    LPDIRECT3DVERTEXBUFFER9 m_fullScreenQuad;
public:
    //usefull for populating an external UI DS
    float* GetDensity() {return &m_gDensity;}
    float* GetIllumDecay() {return &m_gIllumDecay;}
    float* GetWeight() {return &m_gWeight;}
    float* GetDecay() {return &m_gDecay;}
    float* GetExposure() {return &m_gExposure;}
    float* GetTheshHold() {return &m_gTHold;}
    float* GetLightDirectionX(){return &m_lightDirectionScreenSpace.x;}
    float* GetLightDirectionY(){return &m_lightDirectionScreenSpace.y;}

    //All the functionality is down within these functions
    void ResetRenderTarget();
    void RenderAsCamera(bool shadowMapped);
    void SetRenderTarget( LPDIRECT3DTEXTURE9 target);
    void SetNoiseTexture(LPDIRECT3DTEXTURE9 tex){m_noiseTexture = tex;}
    void RenderFullScreenQuad(LPDIRECT3DTEXTURE9 tex);
    void ClearCurrentTarget();
    void GenerateShadowMap();
    void GenerateScene( LPDIRECT3DTEXTURE9 targetTex);
    void RenderAsLight();
    void CreateShadowTexture();
    bool GetUseMeshBool() const;
    bool GetUseExternalTextureBool() const;
    void ChangeLightSource();
    void GenerateGodRays();
    void GenerateFinalTexture();
    void GenerateLightTextureSun();
    void GenerateLightTextureImage();
    void CalculateLightPositionScreenSpace();
    Texture GetFinalTexture();
    Texture GetShadowMap();
    Texture GetSceneTexture();
    Texture GetDarkPassTexture();
    Texture GetLightTexture();
    Texture GetAdititveTexture();
    Texture GetGodRayTexture();
    Texture GetSubtractedLightTexture();
    Texture GetGodRayWithNoiseTexture();
    void TranslateNoiseTexture(float amount);
    int* GetGodRayPasses();
    bool* GetShadowMapBool();
    bool* GetAddingNoiseBool();
    bool* GetGodRayBool();
    bool* GetSkyBoxBool();
    SkyBox* GetSkyBox();
};

#endif
